<?php // -*- mode:php; -*-

// $Id: japmmfd.module 7 2008-09-26 21:07:46Z peter.vizi $

// This file is part of japmmfd.
//
// japmmfd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// japmmfd distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with japmmfd.  If not, see <http://www.gnu.org/licenses/>.

/**
 * @file japmmfd.module
 *
 * This file is part of the japmmfd module.
 *
 * @author peter.vizi@gmail.com
 */

/**
 * Display help and module information
 *
 * @param path which path of the site we're displaying help
 * @param arg array that holds the current path as would be returned from arg() finction
 *
 * @return help text for the path
 */
function japmmfd_help($path, $arg){
    $output = '';
    switch ($path) {
        case "admin/help#japmmfd":
	    $output = '<p>'. t("manages private messaging between registered users") .'</p>';
            break;
    }
    return $output;
} // function japmmfd_help

/**
 * Valid permissions for this module
 *
 * @return array An array of valid permissions for the onthisdate module
 */
function japmmfd_perm() {
    return array('administer private message', 'access private message');
} // function japmmfd_sd_perm()

/**
 * Generate HTML for the japmmfd_sd block
 *
 * @param op the operation from the URL
 * @param delta offset
 *
 * @returns block HTML
 */
function japmmfd_block($op = 'list', $delta = 0) {
    if ($op == "list") {
        $block[0]["info"] = t('Private Messages');
        return $block;
    } else if ($op == 'view') {
        $block = array();
        if (user_access("access private message")) {
	    global $user;
            $block["subject"] = t('New PMs');
	    $query = 'SELECT mid, subject FROM {japmmfd_messages} WHERE rid = %d AND unseen = 1';
	    $results = db_query_range($query, $user->uid, 0, 5);
	    $list = array();
	    while ($result = db_fetch_object($results)) {
		$list[] = l($result->subject, "pm/view/$result->mid");
	    }
            $block["content"] = theme_item_list($list);
        }
        return $block;
    }
} // end function japmmfd_sd_block

/**
 * Loads a message as an object.
 *
 * @param mid the id of the message
 *
 * @return an instance of stdClass representing the message
 */
function pm_load($mid) {
    $query = 'SELECT mid, time, sid, rid, subject, message, refid, unseen FROM {japmmfd_messages} WHERE mid = %d';    
    return db_fetch_object(db_query($query, $mid));;
} // end function pm_load

/**
 * Implementation of hook_menu.
 *
 * @returns an array of menu items defined by this module
 */
function japmmfd_menu() {
    $items = array();
    $items['user/%user/pm'] = array('title' => t('PMs'),
				    'type' => MENU_LOCAL_TASK,
				    'access arguments' => array('access private message'),
				    'page callback' => '_japmmfd_show',
				    'page arguments' => array(1),
				    'weight' => 0);
    $items['pm/view/%pm'] = array('title' => t('Private Message'),
				  'page callback' => '_japmmfd_view',
				  'page arguments' => array(2),
				  'access arguments' => array('access private message'),
				  'type' => MENU_CALLBACK);
    $items['pm/reply/%pm'] = array('title' => t('Reply'),
				   'page callback' => '_japmmfd_reply',
				   'page arguments' => array(2),
				   'access arguments' => array('access private message'),
				   'type' => MENU_CALLBACK);
    $items['pm/delete/%pm'] = array('title' => t('Delete'),
				    'page callback' => '_japmmfd_delete',
				    'page arguments' => array(2),
				    'access arguments' => array('access private message'),
				    'type' => MENU_CALLBACK);
    return $items;
} // end function japmmfd_menu

/**
 * Implementation of hook_cron.
 *
 * We delete those messages which are not required neither by the
 * sender nor by the recipient. This is required because when a user
 * deletes a message it is not physically removed from the database,
 * only a flag is set to 0 (s_copy or r_cop).
 */
function japmmfd_cron() {
    $sql = "DELETE FROM {japmmfd_messages} WHERE s_copy = 0 AND r_copy = 0";
    db_query($sql);
} // end function japmmfd_cron

/**
 * Implementation of hook_theme.
 *
 * Define the template for the private message in pm.tpl.php.
 */
function japmmfd_theme() {
    return array('pm' => array('arguments' => array('pm' => NULL), 
			       'template' => 'pm'));
} // end function japmmfd_theme

/**
 * Implementation of template_preprocess_MODULE.
 *
 * Before rendering pm.tpl.php this function defines some variables.
 *
 * @param variables the array of variables we can manipulate
 */
function template_preprocess_pm(&$variables) {
    global $user;
    $pm = $variables['pm'];
    $sender = user_load(array('uid' => $pm->sid));
    $variables['message'] = nl2br($pm->message);
    $variables['pm_url'] = "pm/view/$pm->mid";
    $variables['title'] = $pm->subject;
    $variables['submitted'] = theme_username($sender).', '.format_date($pm->time);
    $links = array();
    if ($user->uid == $pm->rid) {
	$links['reply'] = array('title' => t('Reply'),
				'href' => "pm/reply/$pm->mid");
    }
    $links['delete'] = array('title' => t('Delete'),
			      'href' => "pm/delete/$pm->mid");
    $variables['links'] = theme_links($links);
} // end function template_preprocess_pm

/**
 * Implementation of hook_forms.
 */
function japmmfd_forms() {
    $forms['japmmfd_send_new']['callback'] = '_japmmfd_form_builder';
    $forms['japmmfd_confirm_delete']['callback'] = '_japmmfd_form_delete';
    return $forms;
} // function japmmfd_forms

/**
 * The callback of the 'pm/delete/%pm' link.
 *
 * Some access control, and display a confirmation form.
 *
 * @param arg the pm which to be deleted
 *
 * @return a form or an error message
 */
function _japmmfd_delete($arg) {
    global $user;
    if ($user->uid == $arg->rid) {
	return drupal_get_form('japmmfd_confirm_delete', $arg);
    } else if ($user->uid == $arg->sid) {
	return drupal_get_form('japmmfd_confirm_delete', $arg);
    }else {
	return t('You are not authorized to delete this message.');
    }
} // end function _japmmfd_delete

/**
 * The callback of the 'pm/reply/%pm' link.
 *
 * Display the form of a private message.
 *
 * @param arg the message we reply to
 *
 * @return the rendered form
 */
function _japmmfd_reply($arg) {
    global $user;
    if ($user->uid == $arg->rid) {
	$form_state = array();
	$form_state['values']['subject'] = 'RE: '.$arg->subject;
	
	$edit = array();
	$edit['rid'] = $arg->sid;
	$edit['sid'] = $arg->rid;
	$edit['refid'] = $arg->mid;
	$edit['subject'] = $arg->subject;
	$edit['message'] = $arg->message;
	$edit['sender'] = user_load(array('uid' => $arg->sid))->name;

	return drupal_get_form('japmmfd_send_new', $edit, t('Reply'));
    } else {
	return t('You are not authorized to reply to this message.');
    }
} // end function _japmmfd_reply

/**
 * The callback of 'user/%user/pm' link.
 *
 * Displays the list of incomming and sent messages, or a form to send
 * message to the user.
 *
 * @param arg the user we are looking at
 *
 * @return rendered html tables or a form to send message
 */
function _japmmfd_show($arg) {
    global $user;
    $output = '';    
    if ($user->uid == $arg->uid) { // show incomming and messages and sent
	drupal_set_title($user->name);

	// incomming messages
	$query = 'SELECT mid, time, sid, subject FROM {japmmfd_messages} WHERE rid = '.
	    $user->uid . ' AND r_copy = 1';
	$header = array(array('data' => t('Time'), 'field' => 'time', 'sort' => 'desc'),
			array('data' => t('Sender'), 'field' => 'sid'),
			array('data' => t('Subject'), 'field'=> 'subject'));
	$query .= tablesort_sql($header);
	$messages = pager_query($query, 10, 1);
	
	$rows = array();

	while ($message = db_fetch_object($messages)) {
	    $from = user_load(array('uid' => $message->sid));
	    
	    $row = array(array('data' => format_date($message->time)),
			 array('data' => theme_username($from)),
			 array('data' => l($message->subject, "pm/view/$message->mid")));
	    $rows[] = $row;
	}

	$form = theme_table($header, $rows, $attributes, t('Incomming messages'));
	$form .= theme('pager', NULL, 10, 1);

	$output .= $form;

	// sent messages
	$query = 'SELECT mid, time, rid, subject FROM {japmmfd_messages} WHERE sid = '.$user->uid.' AND s_copy = 1';
	$header = array(array('data' => t('Time'), 'field' => 'time', 'sort' => 'desc'),
			array('data' => t('Recipient'), 'field' => 'rid'),			
			array('data' => t('Subject'), 'field'=> 'subject'));
	$query .= tablesort_sql($header);
	$messages = pager_query($query, 10, 2);
	
	$rows = array();

	while ($message = db_fetch_object($messages)) {
	    $to = user_load(array('uid' => $message->rid));
	    
	    $row = array(array('data' => format_date($message->time)),
			 array('data' => theme_username($to)),			 
			 array('data' => l($message->subject, "pm/view/$message->mid")));
	    $rows[] = $row;
	}

	$form = theme_table($header, $rows, $attributes, t('Sent messages'));
	$form .= theme('pager', NULL, 10, 2);

	$output .= $form;

	return $output;
    } else { // print a form for sending message
	drupal_set_title(t('Send private message to %user', array('%user' => $arg->name)));
	$edit = array();
	$edit['rid'] = $arg->uid;
	$edit['sid'] = $user->uid;
	$form = drupal_get_form('japmmfd_send_new', $edit, t('Send'));
	return $form;
    }
} // end function _japmmfd_show

/**
 * The callback of the 'pm/view/%pm' link.
 *
 * After some access control the message is displayed.
 *
 * @see pm.tpl.php
 *
 * @param arg the message we are looking at
 *
 * @return error message or the rendered message
 */
function _japmmfd_view($arg) {
    global $user;
    $output = '';
    
    if ($user->uid == $arg->rid) {
	$query = "UPDATE {japmmfd_messages} SET unseen = 0 WHERE mid = %d";
	db_query($query, $arg->mid);
	$output = theme('pm', $arg);
    } else if ($user->uid == $arg->sid) {
	$output = theme('pm', $arg);
    } else {
	$output = t('Your are not authorized to view this message.');
    }
    return $output;
} // end _japmmfd_view

/**
 * Define a form which is desplayed when the user confirms the delete
 * operation.
 *
 * @param form_state the state of the form
 * @param pm the message we are about to delete
 *
 * @return a form to be displayed
 */
function _japmmfd_form_delete(&$form_state, $pm) {
    global $user;
    $form = array();
    $form['mid'] = array('#type' => 'value',
			 '#value' => $pm->mid);
    $form['sid'] = array('#type' => 'value',
			 '#value' => $pm->sid);
    $form['rid'] = array('#type' => 'value',
			 '#value' => $pm->rid);
    $form['delete'] = array('#type' => 'submit', '#value' => t('Delete'));
    $form['cancel'] = array('#type' => 'submit', '#value' => t('Cancel'));
    $form['#submit'] = array('_japmmfd_delete_confirm_submit');
    $form['#redirect'] = "user/$user->uid/pm";
    return $form;
} // end function _japmmfd_form_delete

/**
 * The callback function that is called when the delete form is
 * submitted.
 *
 * @see _japmmfd_form_delete
 *
 * @param form the form that is rendered
 * @param form_state the state of the form
 */
function _japmmfd_delete_confirm_submit($form, &$form_state) {
    global $user;

    if ($form_state['clicked_button']['#value'] == t('Cancel')) {
	drupal_set_message(t('Message not deleted.'));	
    } else {
	if ($form_state['values']['sid'] == $user->uid) {
	    $sql = 'UPDATE {japmmfd_messages} SET s_copy = 0 WHERE mid = %d';
	} else if ($form_state['values']['rid'] == $user->uid) {
	    $sql = 'UPDATE {japmmfd_messages} SET r_copy = 0 WHERE mid = %d';
	}

	db_query($sql, $form_state['values']['mid']);
	drupal_set_message(t('Message deleted.'));
    }
} // end function _japmmfd_delete_confirm_submit

/**
 * Create a form that is displayed to the user when she wants to send
 * a message, or replies to one.
 *
 * @param form_state the state of the form
 * @param edit addititonal parameters
 * @param submit the text on the submit button
 *
 * @return a form array that is to be rendered into html
 */
function _japmmfd_form_builder(&$form_state, $edit, $submit) {
    global $user;
    $form = array();
    $form['rid'] = array('#type' => 'value',
			 '#value' => $edit['rid']);
    $form['sid'] = array('#type' => 'value',
			 '#value' => $edit['sid']);

    $form['refid'] = array('#type' => 'value',
			   '#value' => isset($edit['refid']) ? $edit['refid'] : 0);
    
    $form['subject'] = array('#type' => 'textfield',
			     '#description' => t('Give the subject of your message'),
			     '#required' => TRUE,
			     '#title' => t('Subject'),
			     '#size' => 30
			     );
    if (isset($edit['subject'])) {	
	$form['subject']['#value'] = 'Re: '.$edit['subject'];
    }

    $form['message'] = array('#type' => 'textarea',
			     '#description' => t('Give the content of your message'),
			     '#required' => TRUE,
			     '#title' => t('Message')
			     );
    if (isset($edit['message'])) {
	$form['message']['#value'] = t("%user wrote:\n", array('%user' => $edit['sender']));
	$form['message']['#value'] .= '> '.wordwrap($edit['message'], 75, "\n> ");
    }    

    $form['submit'] = array('#type' => 'submit', '#value' => $submit);
    $form['#submit'] = array('_japmmfd_form_submit');    
    $form['#redirect'] = "user/$user->uid/pm";
    return $form;
} // end function _japmmfd_form_builder

/**
 * The callback function that is called when the private message
 * sending form is submitted.
 *
 * @see _japmmfd_form_builder
 *
 * @param form the form
 * @param form_state the state of the form
 */
function _japmmfd_form_submit($form, &$form_state) {
    $edit = $form_state['clicked_button']['#post'];
    $values = $form_state['values'];
    db_query("INSERT INTO {japmmfd_messages} (time, sid, rid, subject, message, refid, unseen) VALUES (%d, %d, %d, '%s', '%s', %d, %d)", 
	     time(), $values['sid'], $values['rid'], $edit['subject'], $edit['message'], $values['refid'], 1);
    drupal_set_message(t('Message sent.'));
} // end function _japmmfd_form_submit
